<?php

namespace PSC\Controller;

/**
 * Requisição de Controladora
 *
 * Elemento da camada de controle que busca centralizar a captura de valores da
 * requisição utilizando como uma camada especializada, manipulando a informação
 * se esta foi solicitada e não está presente.
 *
 * @category PSC
 * @package  PSC\Controller
 */
class Request
{
    /**
     * Consulta Genérica em Estruturas
     *
     * Centralização de todas as consultas que podem ser efetuadas sobre as
     * informações internas utilizadas, como informações do servidor e
     * parâmetros de requisição. Possibilita a configuração padrão dos valores
     * que são apresentados caso o identificador não seja encontrado.
     *
     * @param  string|array $structure  Estrutura para Consulta
     * @param  string|null  $identifier Identificador do Valor para Solicitação
     * @param  mixed        $default    Valor Padrão Caso Inexistência
     * @return string|mixed Conteúdo Encontrado ou Valor Padrão Apresentado
     */
    protected function _getParam($structure, $identifier = null, $default = null)
    {
        // Resultado Inicial
        $result = $default;
        // Tipagem do Identificador
        if ($identifier === null && is_string($structure)) {
            // Captura de Conteúdo Completo
            $result = $_{$structure};
        } else {
            // Tipagem de Estruturas
            if (is_array($structure)) {
                // Pesquisa Recursiva
                foreach ($structure as $container) {
                    $result = $this->_getParam($container, $identifier, $default);
                    if ($result != $default) break;
                }
            } else {
                // Construção de Código
                eval("if (!empty(\$_{$structure}['$identifier'])) \$result = \$_{$structure}['$identifier'];");
            }
        }
        // Apresentação
        return $result;
    }

    /**
     * Consulta a Informações do Servidor
     *
     * Captura específica para informações provenientes do servidor, utilizando
     * um método que verifica se este está corretamente configurado e
     * apresentando um booleano caso contrário.
     *
     * @param  string      Identificador da Informação
     * @return string|bool Conteúdo Encontrado ou Falso Caso Contrário
     */
    public function getServer($identifier = null)
    {
        // Consulta
        return $this->_getParam('SERVER', $identifier, false);
    }

    /**
     * Captura de Cabeçalhos de Requisição
     *
     * Utiliza as informações apresentadas pelo servidor para verificar se
     * existem dados na requisição conforme identificador apresentado.
     *
     * @param  string      $identifier Identificador do Cabeçalho
     * @return string|bool Conteúdo Encontrado ou Falso Caso Contrário
     */
    public function getHeader($identifier)
    {
        // Conversão
        $identifier = 'HTTP_' . strtoupper(str_replace('-', '_', $identifier));
        // Consulta ao Servidor
        return $this->getServer($identifier);
    }

    /**
     * Método POST Utilizado?
     *
     * Verifica se a requisição foi enviada utilizando o método POST do
     * protocolo HTTP durante a requisição.
     *
     * @return bool Confirmação do Solicitado
     */
    public function isPost()
    {
        return $this->getServer('REQUEST_METHOD') == 'POST';
    }

    /**
     * Utilização de AJAX na Requisição
     *
     * Verifica no cabeçalho da requisição se esta foi executada utilizando
     * técnicas de requisição assíncronas AJAX. Se o cabeçalho com estas
     * informações não estiver sendo enviado, não podemos confirmar este tipo de
     * requisição.
     *
     * @return bool Confirmação do Solicitado
     */
    public function isAjax()
    {
        // Verificação de Requisição AJAX
        return $this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest';
    }

    /**
     * Consulta de Parâmetros em Requisição POST
     *
     * Centralização do acesso aos valores que são enviados durante uma
     * requisição que utiliza o método POST como referência. Caso queiramos
     * capturar o conteúdo completo, somente precisamos apresentar um valor nulo
     * no identificador. Também podemos apresentar um valor padrão caso o
     * elemento solicitado esteja vazio.
     *
     * @param  string|null  $identifier Identificador do Elemento ou Nulo
     * @param  mixed        $default    Valor Padrão para a Consulta
     * @return string|mixed Valor Encontrado ou Conteúdo Padrão Configurado
     */
    public function getPost($identifier = null, $default = null)
    {
        // Consulta
        return $this->_getParam('POST', $identifier, $default);
    }

    /**
     * Consulta de Parâmetros
     *
     * Utiliza um conjunto de pesquisa para encontrar um parâmetro dentro da
     * requisição. Efetua uma busca do valor para o identificador configurado
     * em determinados pontos do sistema. Apresenta o valor padrão caso não seja
     * encontrado.
     *
     * @param  string Identificador do Elemento
     * @param  mixed  Valor Padrão para a Consulta
     * @return mixed  Valor Encontrado ou Valor Padrão para a Consulta
     */
    public function getParam($identifier, $default = null)
    {
        // Consulta
        return $this->_getParam(array('POST', 'GET', 'SERVER'), $identifier, $default);
    }
}

